/*****************************************************************************
Filename    : main.c
Author      : Terrantsh (tanshanhe@foxmail.com)
Date        : 2018-9-22 18:18:54
Description : 实现了RSA2048加密解密的各项功能，并能够进行最大256位的加密操作
*****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>

#include "rsa.h"
#include "keys.h"
#include "ConvertDataType.h"

#define DATA_TYPE_CONVERT (1)

/*
 * RSA2048 encrypt and decrypt
 * include rsa.c/bignum.c/rsa.h/bignum.h/keys.h
 */
static int RSA2048(void){
    int ret;
    rsa_pk_t pk = {0};
    rsa_sk_t sk = {0};
    uint8_t output[256];

    // message to encrypt
    uint8_t input [256] = { 0x21,0x55,0x53,0x53,0x53,0x53};

    unsigned char msg [256];
    uint32_t outputLen, msg_len;
    uint8_t  inputLen;

    // copy keys.h message about public key and private key to the flash RAM
    pk.bits = KEY_M_BITS;
    memcpy(&pk.modulus         [RSA_MAX_MODULUS_LEN-sizeof(key_m) ],  key_m,  sizeof(key_m ));
    memcpy(&pk.exponent        [RSA_MAX_MODULUS_LEN-sizeof(key_e) ],  key_e,  sizeof(key_e ));
    sk.bits = KEY_M_BITS;
    memcpy(&sk.modulus         [RSA_MAX_MODULUS_LEN-sizeof(key_m) ],  key_m,  sizeof(key_m ));
    memcpy(&sk.public_exponet  [RSA_MAX_MODULUS_LEN-sizeof(key_e) ],  key_e,  sizeof(key_e ));
    memcpy(&sk.exponent        [RSA_MAX_MODULUS_LEN-sizeof(key_pe)],  key_pe, sizeof(key_pe));
    memcpy(&sk.prime1          [RSA_MAX_PRIME_LEN - sizeof(key_p1)],  key_p1, sizeof(key_p1));
    memcpy(&sk.prime2          [RSA_MAX_PRIME_LEN - sizeof(key_p2)],  key_p2, sizeof(key_p2));
    memcpy(&sk.prime_exponent1 [RSA_MAX_PRIME_LEN - sizeof(key_e1)],  key_e1, sizeof(key_e1));
    memcpy(&sk.prime_exponent2 [RSA_MAX_PRIME_LEN - sizeof(key_e2)],  key_e2, sizeof(key_e2));
    memcpy(&sk.coefficient     [RSA_MAX_PRIME_LEN - sizeof(key_c) ],  key_c,  sizeof(key_c ));

    inputLen = strlen((const char*)input);

    // public key encrypt
    rsa_public_encrypt(output, &outputLen, input, inputLen, &pk);
    printf("public key encrypt is %d\n",outputLen);
    TRACE(output,outputLen);

    // private key decrypt
    rsa_private_decrypt(msg, &msg_len, output, outputLen, &sk);
    printf("private key decrypt  len is %d\n",msg_len);
    TRACE(msg,msg_len);

    // private key encrypt
    rsa_private_encrypt(output, &outputLen, input, inputLen, &sk);
    printf("private key encrypt len is %d\n",outputLen);
    TRACE(output,outputLen);

    // public key decrypted
    rsa_public_decrypt(msg, &msg_len, output, outputLen, &pk);
    printf("public key decrypted len is %d\n",msg_len);
    TRACE(msg,msg_len);

    return 0;
}
/* RSA2048 function ended */

// message to encrypt
uint8_t inputkey [256] = { 0xa1, 0xfe, 0x12, 0x73, 0x33, 0x16, 0xc7, 0xc7, 0x02, 0xed, 0xcf, 0x00, 0xb4, 0x5b, 0xde, 0xbe }; //AES128 EnCode Key
uint32_t inputkey_Len = 32; //input key len
uint8_t outputkey[256];
uint32_t outputkey_Len = 256;
uint8_t msgkey [256];
uint32_t msgkey_Len;

/**
  * @brief  RSA2048加密
  * @param  plaintext 明文
  * @param  plaintext_Len 明文长度
  * @param  ciphertext 密文
  * @param  ciphertext_Len 密文长度
  * @return none
  * @note   none
  */
void RSA2048EnCode(uint8_t plaintext[256], uint32_t plaintext_Len, uint8_t ciphertext[256], uint32_t ciphertext_Len)
{
    rsa_sk_t sk = {0};

    // copy keys.h message about public key and private key to the flash RAM
    sk.bits = KEY_M_BITS;
    memcpy(&sk.modulus         [RSA_MAX_MODULUS_LEN-sizeof(key_m) ],  key_m,  sizeof(key_m ));
    memcpy(&sk.public_exponet  [RSA_MAX_MODULUS_LEN-sizeof(key_e) ],  key_e,  sizeof(key_e ));
    memcpy(&sk.exponent        [RSA_MAX_MODULUS_LEN-sizeof(key_pe)],  key_pe, sizeof(key_pe));
    memcpy(&sk.prime1          [RSA_MAX_PRIME_LEN - sizeof(key_p1)],  key_p1, sizeof(key_p1));
    memcpy(&sk.prime2          [RSA_MAX_PRIME_LEN - sizeof(key_p2)],  key_p2, sizeof(key_p2));
    memcpy(&sk.prime_exponent1 [RSA_MAX_PRIME_LEN - sizeof(key_e1)],  key_e1, sizeof(key_e1));
    memcpy(&sk.prime_exponent2 [RSA_MAX_PRIME_LEN - sizeof(key_e2)],  key_e2, sizeof(key_e2));
    memcpy(&sk.coefficient     [RSA_MAX_PRIME_LEN - sizeof(key_c) ],  key_c,  sizeof(key_c ));

    //plaintext
    printf("plaintext is:");
    TRACE(plaintext,plaintext_Len);

    // private key encrypt
    rsa_private_encrypt(ciphertext, &ciphertext_Len, plaintext, plaintext_Len, &sk);
    printf("private key encrypt is %d\n",ciphertext_Len);
    TRACE(ciphertext,ciphertext_Len);
}

/**
  * @brief  RSA2048解密
  * @param  ciphertext 密文
  * @param  ciphertext_Len 密文长度
  * @param  plaintext 明文
  * @param  plaintext_Len 明文长度
  * @return none
  * @note   none
  */
void RSA2048DeCode(uint8_t ciphertext[256], uint32_t ciphertext_Len, uint8_t plaintext[32], uint32_t plaintext_Len)
{
    rsa_pk_t pk = {0};

    // copy keys.h message about public key and private key to the flash RAM
    pk.bits = KEY_M_BITS;
    memcpy(&pk.modulus         [RSA_MAX_MODULUS_LEN-sizeof(key_m) ],  key_m,  sizeof(key_m ));
    memcpy(&pk.exponent        [RSA_MAX_MODULUS_LEN-sizeof(key_e) ],  key_e,  sizeof(key_e ));

    // public key decrypt
    rsa_public_decrypt(plaintext, &plaintext_Len, ciphertext, ciphertext_Len, &pk);
    printf("public key decrypt  len is %d\n",plaintext_Len);
    TRACE(plaintext,plaintext_Len);
}

int main(int argc, char const *argv[])
{
    if (DATA_TYPE_CONVERT)
    {
        /* signture */
        char *input_sha256 = "7D22EB415CD5CB8D7F15BF51DA0BDA33F9A1B534E7B6D58F24F12FA9D3028A20";
        char array_sha256[32]={0};
        string2hex(input_sha256, array_sha256);
        memcpy(inputkey,array_sha256,32);
        printf("input_sha256:");
        TRACE(inputkey,32);
    }
    
    clock_t start, finish;
    double  duration;
    start = clock();    // init start time
    if (0)
    {
        RSA2048(); //test running   
    }
    else
    {
        RSA2048EnCode(inputkey,inputkey_Len,outputkey,outputkey_Len);
        RSA2048DeCode(outputkey,outputkey_Len,msgkey,msgkey_Len);
        TRACE(msgkey,32);
    }

    finish = clock();   // print end time
    duration = (double)(finish - start) / CLOCKS_PER_SEC;   // print encrypt and decrypt time
    printf( "%f seconds\n", duration );
    return 0;
}
